#ifndef DECISION_H
#define DECISION_H

//decision system (getting the correct movements...)


#include <cmath>
#include "Util.h"

#include "Movement.h"
#include "Action.h"
#include "States/Ball.h"
#include "States/Player.h"
#include "States/FullState.h"
#include "PlayerParam.h"


//forward-declarations

//FULL_STATE
namespace FInterceptBall
{
    //State (MDP?)
    class State
    {
        double relativeDir;
    public:
        void setRelativeDir(double relativeDir){ this->relativeDir = relativeDir; }
        double getRelativeDir(){ return relativeDir; }
    };

    //MDP def for InterceptBall
    class MDP
    {
        //STATIC?
    };

    class Policy
    {
    public:
        virtual Action* action(State s) = 0;
    };


    class InterceptBall
    {
        State state;

        //HandCoded

        class HandCoded : public Policy
        {
        public:
            Action* action(State s)
            {
                printf("Relativ direction: %lf\n", s.getRelativeDir());
                if (fabs(s.getRelativeDir()) > 36.0f)
                {
                    printf("%lf then turn!\n", s.getRelativeDir());
                    return new Action(Turn, 0, s.getRelativeDir());
                }
                else
                {
                    return new Action(Dash, 50.0f, 0);
                }
            }
        };

        //QLearning

        class QLearning : public Policy
        {
        public:
            Action* action(State s)
            {
                return new Action(Turn, 0, 0);
            }
        };

        friend class HandCoded;

        Policy* mPolicy;

    public:
        InterceptBall(int type)
        {
            //printf("INIT!\n");
            switch(type)
            {
            case 0: mPolicy = new HandCoded(); break;
            case 1: mPolicy = new QLearning(); break;
            }
        }

        void setState()
        {
            //MDP or direct calc of the state!!!

            FullState::instance().mutex.lock();

            Ball aktB = FullState::instance().getBall();
            Player aktP = FullState::instance().getPlayer(PlayerParam::instance().getSide(), PlayerParam::instance().getNum());


            double rDir = aktP.angleFromBody(aktB);
            NormalizeAngleDeg(rDir);
            //printf("%lf\n", rDir);
            state.setRelativeDir(rDir);

            FullState::instance().mutex.unlock();
        }

        Action* nextAction()
        {
            setState();
            //printf("ACTION\n");
            Action* a = mPolicy->action(state);
            //printf("ACTION %d\n", a->getType());
            return a;
        }

        int isDone()
        {
            return 0;
        }
    };
}

//NORMAL_STATE


class Strategy;

//interceptBall, pass, kapura rugas? (Strategy alapjan dont a nextMovement-rol!
class Decision
{
    Strategy* mStrategy;
    //FULL_STATE
    FInterceptBall::InterceptBall* mInterceptBall;
public:

    Decision(int interCeptBallType)
    {
        mInterceptBall = new FInterceptBall::InterceptBall(interCeptBallType);
    }

    void setStrategy(Strategy* mStrategy) { this->mStrategy = mStrategy; }

    //egy movement-et terit vissza, amit a kliens teljes egeszeben vegig csinal
    MovementType nextMovement();

    //egy akciot terit vissza
    Action* nextAction()
    {
        //printf("In nextAction\n");
        switch(this->nextMovement())
        {
        case M_InterceptBall: return mInterceptBall->nextAction(); break;
        case M_Kick1: return new Action(Kick, rand()%70, rand() % 180 - 180); break;
        }
    }
};

#endif // DECISION_H
